import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class ArrayUtilsService {

  constructor() { }

   
  /**
   * 检测某个元素是否存在于数组中，存在则返回true
   * @param array 被检测的数组
   * @param ele 被检测的元素
   */
  has(array:any[],ele:any):boolean{
    return array.some((element,index,array)=>{
      return ele === element;
    });
  }
 
  /**
   * 检测数组中是否有类似的元素，检测指定的几个属性的值都相等，则返回true
   * 要求数组中元素的结构和样本对象的结构相同
   * @param array 被检测的数组
   * @param ele 样本对象，带有N个属性
   * @param fields 要核对的N个属性名构成的字符串数组
   */
  hasSame(array:any[],ele:any,fields:string[]):boolean{
    let sample = this.combineAttr2String(ele,fields);
    console.log('样本：' + sample);
    
    return array.some(
      (item,index,array)=>{
        let detected = this.combineAttr2String(item,fields);
        console.log('检测对象：' + detected);
        return sample === detected;
      }
    )
  }
 
  /**
   * 返回在多个属性上一致的记录构成的数组
   * @param array 源数组
   * @param record 样本记录，对象，数组中的单个元素
   * @param fields 属性构成的字符串数组
   */
  getSames(array:any[],record:any,fields:string[]):any[]{
    let ret = [];
    let sample = this.combineAttr2String(record,fields);
    array.forEach(ele => {
      let detected = this.combineAttr2String(ele,fields);
      if( detected === sample ) ret.push(ele);
    });
 
    return ret;
  }

  /**
   * 制作于2019年12月12日10:31:49
   * 最初设计：业务组件中使用的表格组件是 PrimeNG 的 Table,使用 PrimeNG 的下拉多选组件
   *          被隐藏的列再次显示时会被显示在最后一列，使用 zorro 的下拉多选组件则没有这个问题
   *          并且 PrimeNG 的下拉多选组件高度太高，而 zorro 有官方提供的大中小尺寸
   * @param dataSourceArray 数据源数组
   * @param matchedArray 对照组数组 - 字符串数组
   * @param attrName 对照的属性名称，dataSourceArray中的元素的名称为attrName的属性等于数组matchedArray中的元素则为符合条件可返回
   */
  getSames2<T>(dataSourceArray:T[],matchedArray:string[],attrName:string):T[]{
    let retArray:T[] = [];
    dataSourceArray.forEach(element => {
      let ret = matchedArray.some(
        (ele,index,array)=>{
          return ele === element[attrName];
        }
      )

      if( ret ) retArray.push(element);
    });

    return retArray;
  }
 
  /**
   * 构建在指定的属性上不重复的元素构成的新数组，多个重复的元素中只取第一条
   * @param array 原始数组
   * @param fields 属性名构成的字符串数组
   */
  buildDistArray(array:any[],fields:string[]):any[]{
    let combinArray = [];
    let ret = [];
 
    combinArray.push(this.combineAttr2String(array[0],fields));
    ret.push(array[0]);
 
    array.forEach(ele => {
      let detected = this.combineAttr2String(ele,fields);
 
      let exists = combinArray.some(
        (item,index,array)=>{
          return item === detected;
        }
      )
 
      if(!exists) {
        combinArray.push(detected);
        ret.push(ele);
      }
 
    });
 
    return ret;
  }
 
  /**
   * 返回格式为：attr1=value1,attr2=value2 的字符串
   * @param item 拥有N个属性的对象实例或者数组元素
   * @param fields 要链接的属性名称字符串构成的数组
   */
  combineAttr2String(item:any,fields:string[]){
    let ret = '';
    let i = 0;
    for(i=0;i<fields.length;i++){
      ret = ret + fields[i] + '=' + item[fields[i]] + ',';
    }
    
    let last = ret.substr(ret.length-1,1);
    if( last === ',' ) ret = ret.substr(0,ret.length-1)
    return ret;
  }

  toString(array:string[]):string{
    if( array === undefined || array === null || array.length<=0 ) return '';
    let ret:string='';
    array.forEach(ele => {
      ret = ret + ele + ',';
    });

    if( ret.substring(ret.length-1) === ',' ) ret = ret.substring(0,ret.length - 1);
    return ret;
  }
}
